<?php
/**
 *	KLF Framework
 *
 *	Written by Kristian Oye <kristianoye@gmail.com> on Nov 19, 2011
 *	Copyright (C) 2010-2011
 */
namespace KLF\System\Config
{
	use KLF\KCore;
	use KLF\System\KObject;
	use KLF\System\IDisposable;
	use KLF\System\Errors\KArgumentException;
	
	/**
	 *  Class KCachePool
	 *
	 *  Configuration class that handles creation of a cache pool.
	 *
	 *  @package KLF\System\Config
	 *  @access public
	 *  @author Kristian Oye <kristianoye@gmail.com>
	 *  @since 0.1
	 *  
	 *  @property ICache $Cache 
	 *
	 *  @method KCachePool NewInstance
	 */
	class KCachePool extends KObject implements IDisposable
	{
		/**
		 * Contains the arguments passed to the constructor.
		 * @var array $_ConstructorArgs
		 */
		private $_ConstructorArgs;
		
		/**
		 * Cache pool base type.
		 * 
		 * @var string $_rpropCacheClass
		 */
		protected $_rpropCacheClass;

		/**
		 * The cache objects within the pool.
		 * 
		 * @var array $_rpropCachePool
		 */
		protected $_rpropCachePool;
		
		/**
		 * The cache object that was created from the configuration.
		 * 
		 * @var ICache $_rpropCache
		 */
		protected $_rpropCache;
		
		/**
		 * Returns true if the pool has been initialized, false if not.
		 * 
		 * @var bool $_rpropInitialized
		 */
		protected $_rpropInitialized;
		
		/**
		 * Construct a new cache pool consisting of one or more cache server.
		 */
		public function __construct()
		{
			$this->_ConstructorArgs = func_get_args();
			
			if (count($this->_ConstructorArgs) < 2) {
				throw new KArgumentException("KCachePool constructor requires 2 or more argument(s)");
			}
			$this->_rpropCacheClass = $this->_ConstructorArgs[0];
			$this->_rpropCachePool = array();
			$this->_rpropInitialized = false;
		}
		
		/**
		 * Helper method used within configurations to create instances and return the resulting
		 * ICache object.
		 */
		public static function Create()
		{
			$reflect = new \ReflectionClass(get_called_class());
			$result = $reflect->newInstanceArgs(func_get_args());
			
			return $result;
		}
		
		public function Dispose()
		{
		}
		
		public function Initialize()
		{
			if (!$this->_rpropInitialized)
			{
				$cl = $this->_rpropCacheClass;
				$fqcn = "KLF\\System\\Cache\\".ucfirst($cl);
				$refl = new \ReflectionClass($fqcn);
				$parameterList = $refl->getConstructor()->getParameters();
				
				for($i=1; $i<count($this->_ConstructorArgs); $i++) {
					if (is_array($this->_ConstructorArgs[$i])) {
						$instanceArgs = array();
						$passedArgs = $this->_ConstructorArgs[$i];
						
						foreach($parameterList as $parm) {
							if (isset($passedArgs[$parm->getName()])) {
								array_push($instanceArgs, $passedArgs[$parm->getName()]);
							}
							elseif ($parm->isDefaultValueAvailable()) {
								array_push($instanceArgs, $parm->getDefaultValue());
							}
							elseif (!$parm->isOptional())
							{
								throw new KArgumentException(
									KCore::FS("Parameter '{parm}' is required for '{class}' constructor",
										array('parm' => $parm->getName(), 'class' => $fqcn)));
							}
						}
						if (!isset($this->_rpropCache))
						{
							$this->_rpropCache = ($instance = $refl->newInstanceArgs($instanceArgs));
						}
						else
						{
							$this->_rpropCache->AddCacheMember(($instance = $refl->newInstanceArgs($instanceArgs)));
						}
						array_push($this->_rpropCachePool, $instance);
					}
				}
				$this->_rpropInitialized = true;
			}
			return $this->_rpropCache;
		}
	}
}
